package com.common.filter;


import ch.qos.logback.classic.pattern.ClassOfCallerConverter;
import com.alibaba.fastjson.JSON;
import com.common.cache.IUserCacheRepository;
import com.common.ex.myException.JwtParseException;
import com.common.ex.myException.JwtRenewException;
import com.common.pojo.MyUserDetails;
import com.common.result.JsonResult;
import com.common.result.ResultEnum;
import com.common.utils.JwtUtils;
import com.sun.istack.internal.NotNull;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import lombok.extern.java.Log;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;

/**
 * <p>处理JWT的过滤器</p>
 *
 * <p>此过滤器的主要作用：</p>
 * <ul>
 *     <li>尝试接收客户端的请求中携带的JWT数据</li>
 *     <li>尝试解析JWT数据</li>
 *     <li>将解析得到的用户数据创建为Authentication对象，并存入到SecurityContext中</li>
 * </ul>
 *
 * @author java@tedu.cn
 * @version 3.0
 */
@Slf4j
@Component
public class JwtAuthorizationFilter extends OncePerRequestFilter {
//    public static void main(String[] args) {
//        String a="aaaabbbbbaaaabbbbb";
//        String substring = a.substring(7);
//        System.out.println(a);
//    }


    @Value("${baking.secretKey}")
    private String secretKey;
    @Autowired
    private IUserCacheRepository userCacheRepository;

    private HandlerExceptionResolver handlerExceptionResolver;

    public JwtAuthorizationFilter(HandlerExceptionResolver handlerExceptionResolver) {
        this.handlerExceptionResolver = handlerExceptionResolver;
        log.debug("我是filter的debug");

        log.info("创建过滤器对象：JwtAuthorizationFilter");
    }



    @Override
    protected void doFilterInternal(HttpServletRequest request, @NotNull HttpServletResponse response,
                                    @NotNull FilterChain filterChain) throws ServletException, IOException {
//        log.info(request.getA);
//        String userAgent=request.getHeader("User-Agent");
        System.out.println("喂喂喂听得到吗");
        log.info("处理JWT的过滤器开始处理当前请求……");
        // 直接放行登录和注册的请求
        String[] permitUrls = {"/v1/passport/login", "/v1/user/add", "/v1/user/test",
                "/v1/article/test"};
        String requestURI = request.getRequestURI();
        log.info("请求URI：${}",requestURI);
        log.info("请求URL：{}", requestURI);
        boolean a = Arrays.asList(permitUrls).contains(requestURI);
        log.info("{}",a);

        if (Arrays.asList(permitUrls).contains(requestURI)) {
            log.info("当前请求是登录或注册请求，直接放行");

            filterChain.doFilter(request, response);
            return;
        }


        Claims claims=null;
        String jwt=null;

        // 尝试接收客户端的请求中携带的JWT数据

        jwt = request.getHeader("Authorization");
        if (jwt!=null){
            jwt=jwt.substring(7).trim();
            log.info("jwt:{}",jwt);
        }



//        // 判断JWT的基本有效性（没有必要尝试解析格式明显错误的JWT数据）
//        if (!StringUtils.hasText(jwt) || jwt.length() < JWT_MIN_LENGTH) {
//            // 对于无效的JWT，应该直接放行
//            log.warn("当前请求中，客户端没有携带有效的JWT，将放行");
//            filterChain.doFilter(request, response);
//            return;
//        }

        // 尝试解析JWT数据
        log.info("尝试解析JWT数据……");
        response.setContentType("application/json; charset=utf-8");



        try {
            if (jwt == null) {
                log.warn("用户并没有携带jwt,直接放行");
                filterChain.doFilter(request, response);
                return;

            }
//            log.info(jwt);

            String substring = jwt.substring(7);
            log.info(substring);
            log.info("{}",substring);
            claims = JwtUtils.parse(substring, secretKey);
            if (claims==null){
                throw new  JwtParseException();
            }
//        catch (ExpiredJwtException e) {
//            log.warn("解析JWT时出现异常：ExpiredJwtException");
//            String message = "操作失败，您的登录信息已经过期，请重新登录！";
//            JsonResult jsonResult = new JsonResult(ResultEnum.REDIS_STORAGE_JWT_ERROR ,message);
//            // TODO: 2025/6/30 设置JWT解析失败错误吗
//            PrintWriter writer = response.getWriter();
//            writer.println(JSON.toJSONString(jsonResult));
//            writer.close();
//            return;
//        } catch (SignatureException e) {
//            log.warn("解析JWT时出现异常：SignatureException");
//            String message = "非法访问，你的本次操作已经被记录！";
//            JsonResult jsonResult = JsonResult.fail(ServiceCode.ERR_JWT_SIGNATURE, message);
//            PrintWriter writer = response.getWriter();
//            writer.println(JSON.toJSONString(jsonResult));
//            writer.close();
//            return;
//        } catch (MalformedJwtException e) {
//            log.warn("解析JWT时出现异常：MalformedJwtException");
//            String message = "非法访问，你的本次操作已经被记录！";
//            JsonResult jsonResult = JsonResult.fail(ServiceCode.ERR_JWT_MALFORMED, message);
//            PrintWriter writer = response.getWriter();
//            writer.println(JSON.toJSONString(jsonResult));
//            writer.close();
//            return;
//        } catch(MalformedJwtException malformedJwtException){
//            log.warn("JWT格式损坏");
        } catch (NullPointerException e){
            handlerExceptionResolver.resolveException(request, response, null, e);
            log.warn("用户并没有携带jwt");

        }
        catch (ExpiredJwtException e) {
            handlerExceptionResolver.resolveException(request, response, null, e);
        }catch (JwtParseException e){
            handlerExceptionResolver.resolveException(request,response,null,e);
        }
        catch (Throwable e) {
            log.warn("解析JWT时出现异常：", e);
            String message = "服务器忙，请稍后再试！【同学们，看到这句时，你应该检查服务器端的控制台，并在JwtAuthorizationFilter中解析JWT时添加处理异常的catch代码块】";
            JsonResult jsonResult = new JsonResult(ResultEnum.JWT_PARSE_ERROR);
            PrintWriter writer = response.getWriter();
            writer.println(JSON.toJSONString(jsonResult));
            writer.close();
            return;

        }

            // 从解析结果中获取用户的信息\
        log.info("claims:{}", claims);
            Long uid = claims.get("uid", Long.class);
            ArrayList<String> permission = claims.get("permission", ArrayList.class);
            String addr = claims.get("address", String.class);
            String userAgent = claims.get("userAgent", String.class);

//            Long time = claims.get("time", long.class);
            HashMap hashMap = claims.get("userDetails",HashMap.class);
//            Object parse = JSON.parse(myUserDetailsJson);
            log.info(String.valueOf(hashMap));
//        String userAgent = claims.get(CLAIM_USER_AGENT, String.class);
//        String remoteAddr = claims.get(CLAIM_REMOTE_ADDR, String.class);
            log.info("JWT中的用户uid = {}", uid);
            log.info("JWT中用户权限信息 permission={}", permission);
            log.info("JWT中用户IP地址信息 address={}", addr);
            log.info("JWT中用户权限信息 userAgent  ={}", userAgent);


//        log.debug("JWT中的用户名 = {}", nickname);
//        log.debug("JWT中的浏览器信息 = {}", userAgent);
//        log.debug("JWT中的IP地址 = {}", remoteAddr);

            // 判断此次请求，与当初登录成功时的相关信息是否相同
            log.info("开始检查JWT是否存在盗用的问题……");
            if (!userAgent.equals(request.getHeader("User-Agent"))
                    && !addr.equals(request.getRemoteAddr())) {
                // 本次请求的信息与当初登录时完全不同，则视为无效的JWT
                log.warn("本次请求的信息与当初登录时完全不同，将直接放行，交由后续的组件进行处理");
                filterChain.doFilter(request, response);
                return;
            }
//
//            //判断token是否过期
//            long currentTime = System.currentTimeMillis();
//            if (currentTime - time >= 5 * 60 * 1000) {
//                userCacheRepository.deleteUserState(uid);
//            }

            // 从缓存中读取用户登录信息
            log.info("开始检查缓存中用户的状态……");
            String token = userCacheRepository.getUserToken(uid);
            // 判断缓存中是否存在数据
            if (token == null) {
                // 放行，不会向SecurityContext中存入认证信息，则相当于没有携带JWT
                log.warn("在缓存中无此JWT对应的信息，将直接放行，交由后续的组件进行处理");
                filterChain.doFilter(request, response);
                return;
            }

//        // 检查用户的启用状态
//        Integer userEnable = userState.getEnable();
//        if (!userEnable.equals(ENABLE_STATE_ON)) {
//            userCacheRepository.deleteUserState(userId);
//            String message = "您的账号【" + nickname + "】已经被禁用，将强制下线！";
//            log.warn(message);
//            JsonResult jsonResult = JsonResult.fail(ServiceCode.ERROR_UNAUTHORIZED_DISABLED, message);
//            PrintWriter writer = response.getWriter();
//            writer.println(JSON.toJSONString(jsonResult));
//            writer.close();
//            return;
//        }
    try {
    // 续期缓存中的用户登录信息
        Boolean aBoolean = userCacheRepository.renewToken(uid);
        if (aBoolean==false){
        log.error("token续期失败");
        throw  new JwtRenewException();
        }

    }catch (JwtRenewException e){
        handlerExceptionResolver.resolveException(request, response, null, e);
    }


//        // 从Redis中读取当前用户的权限列表
//        String authoritiesJsonString = permission.getAuthoritiesJsonString();
            log.debug("从Redis中读取当前用户的权限列表 = {}", permission);
//
//        // 将解析得到的用户数据创建为Authentication对象
//        CurrentPrincipal principal = new CurrentPrincipal(); // 当事人
//        principal.setId(userId);
//        principal.setNickname(nickname);

//        List<SimpleGrantedAuthority> authorities
//                = JSON.parseArray(authoritiesJsonString, SimpleGrantedAuthority.class);


            //这里是把普通set集合转换成符合要求的集合
            List<GrantedAuthority> authorities = new ArrayList<>();
            for (String aPermission : permission) {
                authorities.add(new SimpleGrantedAuthority(aPermission));
            }


//            Authentication authentication = new UsernamePasswordAuthenticationToken(
//                    uid, null, authorities);
        MyUserDetails myUserDetails = new MyUserDetails();
            myUserDetails.setUid(uid);


        Authentication authentication = new UsernamePasswordAuthenticationToken(
                myUserDetails, null, authorities);


//        // 将Authentication对象存入到SecurityContext中
            SecurityContext securityContext = SecurityContextHolder.getContext();
            securityContext.setAuthentication(authentication);

            // 过滤器链继续执行，即：放行
            log.debug("验证JWT完毕，已经向SecurityContext中存入认证信息，过滤器将放行");
            filterChain.doFilter(request, response);
        }

}
